This page last changed on Dec 19, 2006 by bowens.

A quick tutorial on how to create and use SLD files to style your map

Introduction Tutorial to Styled Layer Descriptors

Styled Layer Descriptors, or SLD, are what make your maps colorful. They tell the server how the map should be rendered; whether to draw lines in black, or to color them in blue with a nice outline and text labels.

They can turn your map from plain: to nice:

SLD is an XML based language detailed in an open specification available here. This means that SLD files created for GeoServer can be re-used with any WMS that supports SLD. We don't want lock you in to learning yet another way to style maps, so we put the open standard SLD at the center of GeoServer's rendering system.

Now to get even the first image, you need an SLD. Lets look and see how we will do that...

1. SLD Hello World

We will start by creating a simple style for lines.

1.1 Create the SLD File

STEP 1
Make a new file called lines.sld. Save the file anywhere you wish.
In the file, enter the following XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.0.0" 
		xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" 
		xmlns="http://www.opengis.net/sld" 
		xmlns:ogc="http://www.opengis.net/ogc" 
		xmlns:xlink="http://www.w3.org/1999/xlink" 
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<NamedLayer>
		<Name>Default Line</Name>
		<UserStyle>
			<Title>A boring default style</Title>
			<Abstract>A sample style that just prints out a green line</Abstract>
			<FeatureTypeStyle>

				<!-- Rule 1 -->
				<Rule>
					<Name>Rule 1</Name>
					<Title>Green Line</Title>
					<Abstract>A green line with a 2 pixel width</Abstract>

					<LineSymbolizer>
						<Stroke>
							<CssParameter name="stroke">#319738</CssParameter>
							<CssParameter name="stroke-width">2</CssParameter>
						</Stroke>
					</LineSymbolizer>
				</Rule>

		    </FeatureTypeStyle>
		</UserStyle>
	</NamedLayer>
</StyledLayerDescriptor>

The important part, to you, is the <rule>. This will describe what to draw and how to draw it. You can have as many rules as you want. This rule has no restrictions, so it will draw every line in green with a 2 pixel width.

The element that is actually specifying how to draw is the <LineSymbolizer>. In this element we specify the color of the line, <CssParameter name="stroke">#319738</CssParameter>, and the width of the line, <CssParameter name="stroke-width">2</CssParameter>.

1.2 Load Your New SLD

STEP 2
First you will have to start GeoServer. Once it is up and running, navigate to the config/data/style area:
---> --->

In this window, hit new on the left side of the navigation bar:

STEP 3
You will be asked to supply a name for your style (StyleID), lets call it lines. The name does not have to match the filename, but it is good to keep it similar to avoid confusion. Once you have entered the name, hit the New button below it.

STEP 4
The new window you will be taken to will ask for the location of the SLD document. Click on the Browse button and locate the file you created: lines.sld. Click on the file, and hit 'Open' to close the file browse window. The full path should now be in the 'Filename' text field.
Make sure that the check box, Fully Validate against the SLD schema, is checked off. This will make sure our style conforms to the SLD schema.

When you have done all of that, hit the Submit button. This will trigger GeoServer to validate your SLD document and then copy it over to GeoServer's data/styles directory. Everything should work correctly. If it doesn't, there are two types of errors you may get:

  1. "There is already a style by the name of lines.sld stored on GeoServer. Please rename the file and try again". All you have to do in this case is rename your file to something else. This does become an issue when you want to modify and reload the file to test it again. All you have to do is navigate to GeoServer's data/styles directory and delete the SLD document that has the conflicting name.
  2. "Your .SLD file does not conform to the SLD Schema". This error is more complicated, but it usually just the result of a typo or an element that is in the wrong place. This error happens when your SLD document does not conform to the SLD schema. It will also point to where your SLD is wrong. You will have to fix the error, and submit again (hit the back button, and then hit submit).

STEP 5
For the changes to take effect, you must hit the 'Apply' button on the left hand side of the screen.

1.3 Give a FeatureType Your New SLD

In order to see what our style looks like, we need to tell a FeatureType what style to use. Then, whenever we view that FeatureType with the WMS, we will see our style.

STEP 6
Navigate to the FeatureType config menu (Config/Data/FeatureType):
---> --->

We now need to select an existing layer and change its Style. For this tutorial, we will select on of the FeatureTypes that comes installed with GeoServer: tasmania_roads:tasmania_roads
In the drop down list of 'Feature Types', select tasmania_roads:tasmania_roads

Once you have selected it, hit the 'Edit' button.

STEP 7
You should now be in the FeatureType editor screen. Near the top of the screen, under the name of the FeatureType, there will be the Style drop down list. Select your 'lines' style from the list. When you have done that, go down to the bottom of the page and hit the 'Submit' button.

STEP 8
We need to register the change in GeoServer, so once again navigate to the left hand side of the screen and hit the 'Apply' button.

View the Style

It is now time to look at the new style we made.

STEP 9
With GeoServer still running, navigate to the Demos section of the Welcome page. In there, click on Map Preview, or just click on this link http://localhost:8080/geoserver/mapPreview.do.

This page shows you all of the enabled FeatureTypes you have. Locate the topp:tasmania_roads FeatureType and then click on the Preview button to the right of it. This will open up a new window with a MapBuilder view of the dataset. You can also click on this link http://localhost:8080/geoserver/data/generated/topp_tasmania_roads.html to view it.

Hopefully you will see this:

2. SLD Text Symbolizers

We will continue from the previous example where we made a style, lines.sld, that rendered lines green and 2 pixels thick. This time we will add text to the lines that will be read from the roads themselves.

Modify the SLD File to Include Text Symbolizers

STEP 1
Open up your lines.sld file. change it so it looks like this:

<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.0.0" 
		xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" 
		xmlns="http://www.opengis.net/sld" 
		xmlns:ogc="http://www.opengis.net/ogc" 
		xmlns:xlink="http://www.w3.org/1999/xlink" 
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<NamedLayer>
		<Name>Default Line</Name>
		<UserStyle>
			<Title>A boring default style</Title>
			<Abstract>A sample style that just prints out a green line</Abstract>
			<FeatureTypeStyle>

				<!-- Rule 1 -->
				<Rule>
					<Name>Rule 1</Name>
					<Title>Green Line</Title>
					<Abstract>A green line with a 2 pixel width</Abstract>

					<LineSymbolizer>
						<Stroke>
							<CssParameter name="stroke">#319738</CssParameter>
							<CssParameter name="stroke-width">2</CssParameter>
						</Stroke>
					</LineSymbolizer>

					<TextSymbolizer>
						<Label>
							<ogc:PropertyName>TYPE</ogc:PropertyName>
						</Label>

						<Font>
							<CssParameter name="font-family">Times New Roman</CssParameter>
							<CssParameter name="font-style">Normal</CssParameter>
							<CssParameter name="font-size">16</CssParameter>
							<CssParameter name="font-weight">bold</CssParameter>
						</Font>
						
						<Fill>
							<CssParameter name="fill">#FF0000</CssParameter>
						</Fill>
					</TextSymbolizer>

				</Rule>

		    </FeatureTypeStyle>
		</UserStyle>
	</NamedLayer>
</StyledLayerDescriptor>

The part that has changed is the adition of the <TextSymbolizer> element:

<TextSymbolizer>
	<Label>
		<ogc:PropertyName>TYPE</ogc:PropertyName>
	</Label>

	<Font>
		<CssParameter name="font-family">Times New Roman</CssParameter>
		<CssParameter name="font-style">Normal</CssParameter>
		<CssParameter name="font-size">16</CssParameter>
		<CssParameter name="font-weight">bold</CssParameter>
	</Font>
						
	<Fill>
		<CssParameter name="fill">#FF0000</CssParameter>
	</Fill>
</TextSymbolizer>

The parts of this <TextSymbolizer> are:

  • <Label>: What label to give each rendered object. Here we use an attribute of the object, "TYPE". The property name is case sensitive.
  • <Font>: The font and size the label will have.
  • <Fill>: The color that we will fill the font with

There are other options, but we are just going to do something simple for now.

STEP 2
Save your file and keep the name the same, lines.sld.

Head back over to the config/data/style/ page in GeoServer and select your style, lines, from the drop down list. Then hit the 'Edit' button.

STEP 3
In the Style Edit page, use the 'Browse' button to locate your style file, 'lines.sld'. Hit 'Open' to close the browse window, then hit the 'Submit' button.

STEP 4
We need to register our change, so head to the left side of the screen and hit the 'Apply' button.

STEP 5
Lets go and view our changes now. Head to the Map Preview page (http://localhost:8080/geoserver/mapPreview.do) and click on the topp:tasmania_roads preview button (http://localhost:8080/geoserver/data/generated/topp_tasmania_roads.html).

The image should look something like this:

What you will see is the TYPE of the roads displayed. It will not render the label on all of the roads, it will only render the unique values so the road names won't clobber each other. This can become difficult if there are two nearby roads with the same name, but aren't actually the same road. You will get one with a label and one without. To fix this simply add the tag:
<VendorOption name="group">no</VendorOption>
in your <LabelPlacement> tag.

For an indepth document about Labeling, visit the Labeling Options page.

3. Outlines and Filters

This is a very brief introduction to using filters and other text symbolizer techniques with SLDs.

The following SLD document will render all non-highways in the regular green color with a red label. But it will also render the highways with an outline, and give their label an outline.

Here is the SLD:

<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.0.0" 
		xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" 
		xmlns="http://www.opengis.net/sld" 
		xmlns:ogc="http://www.opengis.net/ogc" 
		xmlns:xlink="http://www.w3.org/1999/xlink" 
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<NamedLayer>
		<Name>Default Line</Name>
		<UserStyle>
			<Title>A boring default style</Title>
			<Abstract>A sample style that just prints out a green line</Abstract>
			<FeatureTypeStyle>

				<!-- Rule 1 -->
				<Rule>
					<Name>Rule 1</Name>
					<Title>Green Line</Title>
					<Abstract>A green line with a 2 pixel width</Abstract>

					<ogc:Filter>
						<ogc:Not>
							<ogc:PropertyIsEqualTo>
								<ogc:PropertyName>TYPE</ogc:PropertyName>
								<ogc:Literal>highway</ogc:Literal>
							</ogc:PropertyIsEqualTo>
						</ogc:Not>
					</ogc:Filter>

					<LineSymbolizer>
						<Stroke>
							<CssParameter name="stroke">#319738</CssParameter>
							<CssParameter name="stroke-width">2</CssParameter>
						</Stroke>
					</LineSymbolizer>

					<TextSymbolizer>
						<Label>
							<ogc:PropertyName>TYPE</ogc:PropertyName>
						</Label>

						<Font>
							<CssParameter name="font-family">Times New Roman</CssParameter>
							<CssParameter name="font-style">Normal</CssParameter>
							<CssParameter name="font-size">16</CssParameter>
							<CssParameter name="font-weight">bold</CssParameter>
						</Font>

						<Fill>
							<CssParameter name="fill">#FF0000</CssParameter>
						</Fill>
					</TextSymbolizer>

				</Rule>

				<!-- Rule 2 -->
				<Rule>
					<Name>Rule 2</Name>
					<Title>Outlined Highways</Title>
					<Abstract>A gray outline and white fill, with a 8 pixel width</Abstract>

					<ogc:Filter>
						<ogc:PropertyIsEqualTo>
							<ogc:PropertyName>TYPE</ogc:PropertyName>
							<ogc:Literal>highway</ogc:Literal>
						</ogc:PropertyIsEqualTo>
					</ogc:Filter>

					<LineSymbolizer>
						<Stroke>
							<CssParameter name="stroke">#444444</CssParameter>
							<CssParameter name="stroke-width">8</CssParameter>
						</Stroke>
					</LineSymbolizer>
					<LineSymbolizer>
						<Stroke>
							<CssParameter name="stroke">#999999</CssParameter>
							<CssParameter name="stroke-width">4</CssParameter>
						</Stroke>
					</LineSymbolizer>

					<TextSymbolizer>
						<Label>
							<ogc:PropertyName>TYPE</ogc:PropertyName>
						</Label>

						<Font>
							<CssParameter name="font-family">Times New Roman</CssParameter>
							<CssParameter name="font-style">Normal</CssParameter>
							<CssParameter name="font-size">18</CssParameter>
							<CssParameter name="font-weight">bold</CssParameter>
						</Font>

						<Halo>
							<Radius>
								<ogc:Literal>2</ogc:Literal>
							</Radius>
							<Fill>
								<CssParameter name="fill">#FFF88B</CssParameter>
								<CssParameter name="fill-opacity">0.85</CssParameter>				
							</Fill>
						</Halo>

						<Fill>
							<CssParameter name="fill">#FF0000</CssParameter>
						</Fill>
					</TextSymbolizer>
					
				</Rule>

		    </FeatureTypeStyle>
		</UserStyle>
	</NamedLayer>
</StyledLayerDescriptor>

What we have done is supply another rule to our SLD.

Rule 1

The first rule will render all non-highways with a green line. To determine what roads are not highways, we use a <filter>:

<ogc:Filter>
	<ogc:Not>
		<ogc:PropertyIsEqualTo>
			<ogc:PropertyName>TYPE</ogc:PropertyName>
			<ogc:Literal>highway</ogc:Literal>
		</ogc:PropertyIsEqualTo>
	</ogc:Not>
</ogc:Filter>

This rule will only render the line if its 'TYPE' is not equal to "highway". The 'not' is specified by wrapping the "PropertyIsEqualTo" element in an <ogc:Not> element.
If the TYPE is 'highway', then the rule is not rendered for that particular line segment.

Other useful filter elements are:

  • <ogc:PropertyIsLessThan>
  • <ogc:PropertyIsGreaterThan>

Rule 2

This rule uses a filter to determine if the road's TYPE is equal to "highway". If it is, it will render two lines for the road. The first is a thick dark gray line, the other is a thinner light gray line. They are rendered in the order that they are specified.

The other thing it will do is render the labels using a <halo> in the <TextSymbolizer>. The halo is essentially a buffer outline of the text.

<Halo>
	<Radius>
		<ogc:Literal>2</ogc:Literal>
	</Radius>
	<Fill>
		<CssParameter name="fill">#FFF88B</CssParameter>
		<CssParameter name="fill-opacity">0.85</CssParameter>				
	</Fill>
</Halo>

Output

If it all worked out, the result should look something like this:

4. What SLDs are, a text approach

SLD (Styled Layer Descriptor) is a specification put out by the OGC, that defines an XML language to allow users to define symbolization of their feature data. It was written to be a complement to their Web Map Service (WMS) specification, by extending it to allow users a way to define how they want to visualize their features.

The spec is available here?

In the original WMS versions a user could ask for a 'style', specified by name, to view the map in. Each server advertised what 'styles' could be asked for with which layers. This was pretty inflexible, the only control a user had was to pick a name for a style, if the map didn't look the way she wanted it to then that was just too bad.

It became obvious that it would be nice for users to be able to tell a server what they would actually like the style to look like. And thus came SLD, a nice little xml language for machines to understand how a human would like a map to look.

So for each layer you could say 'color all my line features blue', or 'make all polygon borders black, and the insides purple', or even 'use this little triangle graphic for all my points'.

But you can also define even more complex functionality. You can define the style rules based on attributes of the features in a layer. To pull an example from the SLD spec itself:
'For example, in a roads data set, style highways with a three-pixel red line; style four-lane roads in a two-pixel black line; and style two-lane roads in a one-pixel black line.'

The spec was originally meant for WMS, you could define an SLD document and send it to a server, and it would return the layer in the style you specified. But it has proven more useful than that. One way is to combine it with a WFS. There is a notion of a Cascading WMS, which would just be a middle layer between a WFS, adding the appropriate style and portraying it as the user wanted. A WFS defines the data, the WMS just adds the style information. GeoServer plans to have cascading WMS capabilities for version 1.3. The other place it's proven useful is as part of applications themselves. A good client could take a SLD file and apply that to the WFS response (GML) that it receives (this is what Sonny's client does, it's actually outside the original reason for the SLD spec, but a good use of it, as an SLD file could be passed to different clients ? you can send the WFS link and an SLD, so that they could actually get the data, instead of just a WMS response, which is simply a picture of the data). It's also useful as a way to define styles on the server itself. In OGC speak these are 'named' styles, as opposed to user defined ones. For user defined you send an sld document directly to the server, for a named one you just request the style by it's name. This is what GeoServer does, as there was already SLD support in GeoTools, and it's a solid way to define styles. GeoServer's styles are configured directly by reading SLD files.

There is also having SLD files themselves be passed about the read. I believe there was a discussion spec for a server that would hold SLD files, and you could request them from the server, a sort of SLD service. The SLD extensions to a WMS also describe PutStyle and GetStyle operations, where a user could upload his style to the server, and others could download the files themselves.

I don't have time right now to run through a bunch of sample SLD files, which I will in a final tutorial. You can refer to 'named' styles, but the more interesting part is the user defined stuff. There are two main sections for user defined styles (I think, I need to research this more, my SLD skills aren't nearly as strong as my WFS skills). A Rule defines in what cases the style should be applied. They can use the whole suite of OGC filters, so you really can define a lot. Complex stuff like coloring based on math expressions (add the unemployed, underemployed and temporary employed attributes, divide by total number of people, to give percentage of workers at less than full employment, and define the opacity based on the resulting number). They can also be defined for map scales, so things like only show two lane highways when we are at a certain resolution In a rule you can also define a 'legend graphic', which will show what means what on the map, by pointing to some external file (GeoServer has aspirations to create dynamic legend graphics based on the SLD definitions).

Then there are 5 types of symbolizers you can use to actually portray the features, line, polygon, point, text, and raster. A line symbolizer will define a 'stroke' for a line geometry. A stroke is made up of a couple elements, allowing you to specify a color, or a graphic, along with things like opacity, width, joins between lines, a dash pattern and a dash offset.

A Polygon Symbolizer has a geometry and a stroke, just like a line symbolizer, but also has a 'fill', defining what color to put in the center. Can be straight color, or a graphic, of varying opacity and the like.

A point symbolizer is made up of a geometry and a Graphic. A graphic is made of either an External Graphic, or a Mark, and has an opacity, a size, and a rotation. Opacity is the same as for the other symbolizers, Size is the absolute size of the graphic in pixels (default is to be dynamic), and rotation defines the rotation of the graphic in the clockwise dimension in decimal degrees. A Mark has a well known name (like square, circle, star, ect.), and a fill and a stroke. An External Graphic uses an xlink to refer to the location of an resource on the web to use to represent the point.

(Need to wrap this up, so my explanations are getting shorter).

A text symbolizer is made up of a Geometry, a Label, a Font, a LabelPlacement, a Halo, and a Fill.

A raster symbolizer consists of a Geometry, opacity, channel selection, overlap behavior, color map, contrast enhancement, shaded relief and image outline.

(please excuse the lack of formatting and far from complete information, I will come back to it)

5. Further Reading

If you have gotten this far, why not go further? Check out the GeoServer docs page for more information on SLDs, and read up on the SLD specification to see all the tags you can use. It is a good read.

Also, head back to our main SLD page, especially Dave's advanced style tutorial.

Document generated by Confluence on Jan 16, 2008 23:27